package com.aote.serialnumber;

import java.lang.reflect.Constructor;
import java.util.Collection;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.TreeSet;

import org.w3c.dom.Element;

import com.browsesoft.PropertiesService;
import com.browsesoft.Tools;
import com.browsesoft.dbtools.DBTools;
import com.browsesoft.tools.BSCalendar;

/**
 * 编号
 */
public class IncreaseSerialNumber {

	/**
	 * 表名
	 */
	private static String tableName = "f_serialnumber";

	/**
	 * 初始化值
	 */
	private static String initValue = "1";

	/**
	 * 名称
	 */
	private String name = "";

	/**
	 * 数据
	 */
	private Hashtable datas = new Hashtable();

	/**
	 * 保存具体编号
	 */
	private String number = null;

	/**
	 * 失效属性
	 */
	private Collection expirations = new TreeSet();

	/**
	 * 规则初始化器
	 */
	private InitRule rule = null;

	public IncreaseSerialNumber(String name) {
		this.name = name;
		init();
		this.rule = this.createInitRule();
	}

	public IncreaseSerialNumber(Hashtable table) {
		this.name = (String) table.get("id");
		this.datas = table;
		this.rule = this.createInitRule();
		String ids = (String) table.get("expirations");
		if (ids != null) {
			this.expirations = Tools.stringToLinkedList(ids);
		}
	}

	/**
	 * 创建初始化器
	 * 
	 * @return
	 */
	private InitRule createInitRule() {
		try {
			Element elem = (Element) PropertiesService.getDocument()
					.getElementsByTagName(this.name).item(0);
			String className = elem.getAttribute("className");
			Class c = Class.forName(className);
			Constructor cons = c
					.getConstructor(new Class[] { this.getClass() });
			InitRule rule = (InitRule) cons.newInstance(new Object[] { this });
			if (this.rule != null && this.rule.isInit()) {
				init();
				DBTools.update(tableName, this.name, this.datas);
			}
			return rule;
		} catch (Exception e) {
			System.out.println("没有在属性文件中找到标记为" + this.name + "得初始化规则配置");
			return null;
		}
	}

	/**
	 * 插入数据
	 * 
	 */
	public void insert() {
		try {
			DBTools.insert(tableName, this.datas);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 初始化
	 * 
	 */
	public void init() {
		this.datas.put("id", this.name);
		this.datas.put("tablename", tableName);
		this.datas.put("value", initValue);
		this.datas.put("f_date", BSCalendar.now().toString());
		this.datas.put("expirations", "");
	}

	/**
	 * 得到编号
	 */
	public String getSerialNumber(String length) {
		try {
			// 根据长度得到当前编号
			String result = this.getNum();
			this.number = result;
			if (length == null || length.equals("")) {
				return result;
			}
			// 长度不足得载编号前加0
			int defLength = Integer.parseInt(length);
			int numLength = result.length();
			for (int i = 0; i < (defLength - numLength); i++) {
				result = "0" + result;
			}
			return result;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 更新编号
	 */
	public void updateNum() {
		try {
			if (this.expirations.contains(number)) {
				this.expirations.remove(number);
				String str = Tools.LinkedListTostring(new LinkedList(
						this.expirations));
				this.datas.put("expirations", str);
			} else {
				int i = Integer.parseInt(number) + 1;
				this.datas.put("value", i + "");
			}
			DBTools.update(tableName, this.name, this.datas);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 得属性
	 */
	public Hashtable getAttributes() {
		return this.datas;
	}

	/**
	 * 得编号
	 */
	private String getNum() {
		String expnumber = this.getExpirationNum();
		if (expnumber != null) {
			return expnumber;
		}
		return (String) this.datas.get("value");
	}

	/**
	 * 得到失效编号
	 */
	private String getExpirationNum() {
		Iterator iter = expirations.iterator();
		if (!iter.hasNext()) {
			return null;
		}
		String number = (String) iter.next();
		return number;
	}

	/**
	 * 添加失效编号
	 */
	public void addExpirationNum(String number) {
		try {
			expirations.add(number);
			String str = Tools.LinkedListTostring(new LinkedList(
					this.expirations));
			this.datas.put("expirations", str);
			DBTools.update(tableName, this.name, this.datas);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 得编号名字
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * 得最后一次编号
	 */
	public String getLastNumber() {
		return this.number;
	}

	public String getNumberName() {
		return (String) this.datas.get("id");
	}
}
